class TestCrankGearsPulley extends Test
{
    private m_joint1:Box2D.Dynamics.Joints.b2RevoluteJoint;
    private m_joint2:Box2D.Dynamics.Joints.b2PrismaticJoint;

    public m_gJoint1:Box2D.Dynamics.Joints.b2RevoluteJoint;
    public m_gJoint2:Box2D.Dynamics.Joints.b2RevoluteJoint;
    public m_gJoint3:Box2D.Dynamics.Joints.b2PrismaticJoint;
    public m_gJoint4:Box2D.Dynamics.Joints.b2GearJoint;
    public m_gJoint5:Box2D.Dynamics.Joints.b2GearJoint;

    public constructor(sprite:DebugDraw)
    {
        super(sprite);
        this.createScene();
    }

    private createScene():void
    {
        let ground:Box2D.Dynamics.b2Body = this.m_world.GetGroundBody();
        let body:Box2D.Dynamics.b2Body;
        var circleBody:Box2D.Dynamics.b2Body;
        let sd:Box2D.Collision.Shapes.b2PolygonShape;
        let bd:Box2D.Dynamics.b2BodyDef;
        let fixtureDef:Box2D.Dynamics.b2FixtureDef = new Box2D.Dynamics.b2FixtureDef();

        //crank
        {
            sd = new Box2D.Collision.Shapes.b2PolygonShape();
            sd.SetAsBox(7.5 / this.m_physScale, 30.0 / this.m_physScale);
            fixtureDef.shape = sd;
            fixtureDef.density = 1.0;

            let rjd:Box2D.Dynamics.Joints.b2RevoluteJointDef = new Box2D.Dynamics.Joints.b2RevoluteJointDef();
            let prevBody:Box2D.Dynamics.b2Body = ground;

            bd = new Box2D.Dynamics.b2BodyDef();
            bd.type = Box2D.Dynamics.b2Body.b2_dynamicBody;
            bd.position.Set(100.0 / this.m_physScale, (360 - 105.0) / this.m_physScale);
            body = this.m_world.CreateBody(bd);
            body.CreateFixture(fixtureDef);

            rjd.Initialize(prevBody, body, new Box2D.Common.Math.b2Vec2(100.0 / this.m_physScale, (360 - 75.0)/ this.m_physScale));
            rjd.motorSpeed = 1.0 * -Math.PI;
            rjd.maxMotorTorque = 5000;
            rjd.enableMotor = true;

            this.m_joint1 = this.m_world.CreateJoint(rjd) as Box2D.Dynamics.Joints.b2RevoluteJoint;

            prevBody = body;

            //define follower.
            sd = new Box2D.Collision.Shapes.b2PolygonShape();
            sd.SetAsBox(7.5 / this.m_physScale, 60.0 / this.m_physScale);
            fixtureDef.shape = sd;
            
            bd.position.Set(100.0 / this.m_physScale, (360 - 195.0) / this.m_physScale);
            //bd.fixedRotation = true;
            body = this.m_world.CreateBody(bd);
            body.CreateFixture(fixtureDef);
            
            rjd.Initialize(prevBody, body, new Box2D.Common.Math.b2Vec2(100 / this.m_physScale, (360 - 135) / this.m_physScale));
            rjd.enableMotor = false;
            this.m_world.CreateJoint(rjd);

            prevBody = body;

            // define piston
            sd = new Box2D.Collision.Shapes.b2PolygonShape();
            sd.SetAsBox(22.5 / this.m_physScale, 22.5 / this.m_physScale);
            fixtureDef.shape = sd;
            bd.position.Set(100 / this.m_physScale, (360 - 255)/ this.m_physScale);
            body =this.m_world.CreateBody(bd);
            body.CreateFixture(fixtureDef);

            rjd.Initialize(prevBody, body, new Box2D.Common.Math.b2Vec2(100 / this.m_physScale, (360 - 255) / this.m_physScale));
            this.m_world.CreateJoint(rjd);

            var pjd:Box2D.Dynamics.Joints.b2PrismaticJointDef = new Box2D.Dynamics.Joints.b2PrismaticJointDef();
            pjd.Initialize(ground, body, new Box2D.Common.Math.b2Vec2(100 / this.m_physScale, (360 - 255)/ this.m_physScale), new Box2D.Common.Math.b2Vec2(0.0, 1.0));
            pjd.maxMotorForce = 500;
            //pjd.motorSpeed = 1;
            //pjd.enableMotor = true;

            this.m_joint2 = this.m_world.CreateJoint(pjd) as Box2D.Dynamics.Joints.b2PrismaticJoint;

            //create a payload
            sd = new Box2D.Collision.Shapes.b2PolygonShape();
            sd.SetAsBox(22.5 / this.m_physScale, 22.5 / this.m_physScale);
            fixtureDef.shape = sd;
            fixtureDef.density = 2.0;
            bd.position.Set(100 / this.m_physScale, (360 - 345) / this.m_physScale);
            body = this.m_world.CreateBody(bd);
            body.CreateFixture(fixtureDef);
        }
        //gear
        {
            let circle1:Box2D.Collision.Shapes.b2CircleShape = new Box2D.Collision.Shapes.b2CircleShape(25 / this.m_physScale);
            fixtureDef.shape = circle1;
            fixtureDef.density = 5.0;

            let bd1:Box2D.Dynamics.b2BodyDef = new Box2D.Dynamics.b2BodyDef();
            bd1.type = Box2D.Dynamics.b2Body.b2_dynamicBody;
            bd1.position.Set(200 / this.m_physScale, 360 / 2 / this.m_physScale);
            var body1:Box2D.Dynamics.b2Body = this.m_world.CreateBody(bd1);
            body1.CreateFixture(fixtureDef);

            let jd1:Box2D.Dynamics.Joints.b2RevoluteJointDef = new Box2D.Dynamics.Joints.b2RevoluteJointDef();
            jd1.Initialize(ground, body1, bd1.position);
            this.m_gJoint1 = this.m_world.CreateJoint(jd1) as Box2D.Dynamics.Joints.b2RevoluteJoint;

            let circle2:Box2D.Collision.Shapes.b2CircleShape = new Box2D.Collision.Shapes.b2CircleShape(50/ this.m_physScale);
            fixtureDef.shape = circle2;
            fixtureDef.density = 5.0;

            let bd2:Box2D.Dynamics.b2BodyDef = new Box2D.Dynamics.b2BodyDef();
            bd2.type = Box2D.Dynamics.b2Body.b2_dynamicBody;
            bd2.position.Set(275 / this.m_physScale, 360 / 2 / this.m_physScale);
            var body2:Box2D.Dynamics.b2Body = this.m_world.CreateBody(bd2);
            body2.CreateFixture(fixtureDef);

            let jd2:Box2D.Dynamics.Joints.b2RevoluteJointDef = new Box2D.Dynamics.Joints.b2RevoluteJointDef();
            jd2.Initialize(ground, body2, bd2.position);
            this.m_gJoint2 = this.m_world.CreateJoint(jd2) as Box2D.Dynamics.Joints.b2RevoluteJoint;

            let box:Box2D.Collision.Shapes.b2PolygonShape = new Box2D.Collision.Shapes.b2PolygonShape();
            box.SetAsBox(10 / this.m_physScale, 100 / this.m_physScale);
            fixtureDef.shape = box;
            fixtureDef.density = 5.0;

            let bd3:Box2D.Dynamics.b2BodyDef = new Box2D.Dynamics.b2BodyDef();
            bd3.type = Box2D.Dynamics.b2Body.b2_dynamicBody;
            bd3.position.Set(335 / this.m_physScale, 360 / 2 / this.m_physScale);
            var body3:Box2D.Dynamics.b2Body = this.m_world.CreateBody(bd3);
            body3.CreateFixture(fixtureDef);

            let jd3:Box2D.Dynamics.Joints.b2PrismaticJointDef = new Box2D.Dynamics.Joints.b2PrismaticJointDef();
            jd3.Initialize(ground, body3, bd3.position, new Box2D.Common.Math.b2Vec2(0,1));
            jd3.lowerTranslation = -25 / this.m_physScale;
            jd3.upperTranslation = 100 / this.m_physScale;
            jd3.enableLimit = true;

            this.m_gJoint3 = this.m_world.CreateJoint(jd3) as Box2D.Dynamics.Joints.b2PrismaticJoint;

            let jd4:Box2D.Dynamics.Joints.b2GearJointDef = new Box2D.Dynamics.Joints.b2GearJointDef();
            jd4.bodyA = body1;
            jd4.bodyB = body2;
            jd4.joint1 = this.m_gJoint1;
            jd4.joint2 = this.m_gJoint2;
            jd4.ratio = circle2.GetRadius() / circle1.GetRadius();
            this.m_gJoint4 = this.m_world.CreateJoint(jd4) as Box2D.Dynamics.Joints.b2GearJoint;

            let jd5:Box2D.Dynamics.Joints.b2GearJointDef = new Box2D.Dynamics.Joints.b2GearJointDef();
            jd5.bodyA = body2;
            jd5.bodyB = body3;
            jd5.joint1 = this.m_gJoint2;
            jd5.joint2 = this.m_gJoint3;
            jd5.ratio = -1.0 / circle2.GetRadius();
            this.m_gJoint5 = this.m_world.CreateJoint(jd5) as Box2D.Dynamics.Joints.b2GearJoint;
        }

       // /*
        {
            //pulley
            //let body2:Box2D.Dynamics.b2Body;

            sd = new Box2D.Collision.Shapes.b2PolygonShape();
            sd.SetAsBox(50 / this.m_physScale, 20 / this.m_physScale);
            fixtureDef.shape = sd;
            fixtureDef.density = 5.0;

            bd = new Box2D.Dynamics.b2BodyDef();
            bd.type = Box2D.Dynamics.b2Body.b2_dynamicBody;

            bd.position.Set(480 / this.m_physScale, 200 / this.m_physScale);
            body2 = this.m_world.CreateBody(bd);
            body2.CreateFixture(fixtureDef);

            
            var pulleyDef:Box2D.Dynamics.Joints.b2PulleyJointDef = new Box2D.Dynamics.Joints.b2PulleyJointDef();
            
            let anchor1:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2(335 / this.m_physScale, 180 / this.m_physScale);
            let anchor2:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2(480 / this.m_physScale, 180 / this.m_physScale);
            let groundAnchor1:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2(335 / this.m_physScale, 50 / this.m_physScale);
            let groundAnchor2:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2(480 / this.m_physScale, 50 / this.m_physScale);
            pulleyDef.Initialize(body3, body2, groundAnchor1,groundAnchor2, anchor1, anchor2, 2.0);
            pulleyDef.maxLengthA = 200 / this.m_physScale;
            pulleyDef.maxLengthB = 150 / this.m_physScale;

            this.m_world.CreateJoint(pulleyDef) as Box2D.Dynamics.Joints.b2PullyJoint;
            

            let circ:Box2D.Collision.Shapes.b2CircleShape = new Box2D.Collision.Shapes.b2CircleShape(40 / this.m_physScale);
            fixtureDef.shape = circ;
            fixtureDef.friction = 0.3;
            fixtureDef.restitution = 0.3;
            fixtureDef.density = 5.0;
            bd.position.Set(485 / this.m_physScale, 100 / this.m_physScale);
            body1 = circleBody = this.m_world.CreateBody(bd);
            body1.CreateFixture(fixtureDef);

        }
        //*/

        //line joint
        {
            sd = new Box2D.Collision.Shapes.b2PolygonShape();
            sd.SetAsBox(7.5 / this.m_physScale, 30 / this.m_physScale);
            fixtureDef.shape = sd;
            fixtureDef.density = 1.0;

            bd = new Box2D.Dynamics.b2BodyDef();
            bd.type = Box2D.Dynamics.b2Body.b2_dynamicBody;
            bd.position.Set(500 / this.m_physScale, 500 / 2/ this.m_physScale);
            body = this.m_world.CreateBody(bd);
            body.CreateFixture(fixtureDef);

            //linejoint 和prismaticjoint 啥区别？？？
            let ljd:Box2D.Dynamics.Joints.b2LineJointDef = new Box2D.Dynamics.Joints.b2LineJointDef();
            ljd.Initialize(ground, body, body.GetPosition(),new Box2D.Common.Math.b2Vec2(0.4, 0.6));
            ljd.lowerTranslation = -1;
            ljd.upperTranslation = 1;
            ljd.enableLimit= true;
            //ljd.maxMotorForce = 1000;
            //ljd.motorSpeed = -0.1;
            //ljd.enableMotor = true;

            this.m_world.CreateJoint(ljd);
        }

        ///*
        //friction joint
        {
            let fjd:Box2D.Dynamics.Joints.b2FrictionJointDef = new Box2D.Dynamics.Joints.b2FrictionJointDef();
            fjd.Initialize(circleBody, ground, circleBody.GetPosition());
            fjd.collideConnected = true;
            fjd.maxForce = 200;
            this.m_world.CreateJoint(fjd);
        }
        //*/

        //weld joint
        if(false)
        {
            let wjd:Box2D.Dynamics.Joints.b2WeldJointDef = new Box2D.Dynamics.Joints.b2WeldJointDef();
            wjd.Initialize(circleBody, body, circleBody.GetPosition());
            this.m_world.CreateJoint(wjd);
        }
    }
}
